﻿﻿﻿﻿﻿﻿﻿﻿﻿﻿﻿﻿﻿﻿﻿using jiuyuan.数据.基础数据类;
using jiuyuan.数据.怪物类;
using jiuyuan.数据.玩家类;
using jiuyuan.服务;
using Microsoft.Extensions.Logging;
using System.Collections.Concurrent;
using System.Collections.Generic;

namespace jiuyuan.管理器;

// 战斗上下文
public class 战斗上下文
{
    public Guid 战斗ID { get; set; } = Guid.CreateVersion7();
    public 副本配置 副本 { get; set; } = null!;
    public List<玩家> 玩家队伍 { get; set; } = [];
    public List<怪物> 怪物队伍 { get; set; } = [];
    public int 当前回合数 { get; set; } = 0;
    public bool 是否结束 { get; set; } = false;
    public bool 玩家胜利 { get; set; } = false;
    public Dictionary<Guid, AI决策> 玩家决策 { get; set; } = [];
    public 战斗管理器 战斗管理器 { get; set; } = null!;
    
    // 添加回合制战斗系统相关属性
    public List<jiuyuan.服务.行动单位> 当前回合行动顺序 { get; set; } = [];
    public int 当前行动单位索引 { get; set; } = 0;
    public bool 等待玩家决策 { get; set; } = false;
    public DateTime 回合开始时间 { get; set; } = DateTime.Now;
    public int 回合时间限制 { get; set; } = 30; // 回合时间限制（秒）
    
    // 添加获取友方和敌方单位的方法
    public List<战斗单位> 获取友方单位(战斗单位 单位)
    {
        if (单位 is 玩家)
        {
            return 玩家队伍.Cast<战斗单位>().ToList();
        }
        else
        {
            return 怪物队伍.Cast<战斗单位>().ToList();
        }
    }
    
    public List<战斗单位> 获取敌方单位(战斗单位 单位)
    {
        if (单位 is 玩家)
        {
            return 怪物队伍.Cast<战斗单位>().ToList();
        }
        else
        {
            return 玩家队伍.Cast<战斗单位>().ToList();
        }
    }
}

// 战斗结果
public class 战斗结果
{
    public bool 玩家胜利 { get; set; }
    public int 获得经验 { get; set; }
    public List<掉落物品> 获得物品 { get; set; } = [];
    public int 战斗回合数 { get; set; }
}

// AI决策
public class AI决策
{
    public string 行动类型 { get; set; } = "攻击"; // 攻击/技能/防御/物品
    public string? 技能名称 { get; set; }
    public 战斗单位? 目标 { get; set; }
    public List<战斗单位> 目标列表 { get; set; } = [];
    public DateTime 提交时间 { get; set; } = DateTime.Now; // 添加提交时间
    
    // 添加构造函数
    public AI决策() { }
    
    public AI决策(string 行动类型, string? 技能名称 = null, 战斗单位? 目标 = null)
    {
        this.行动类型 = 行动类型;
        this.技能名称 = 技能名称;
        this.目标 = 目标;
        this.目标列表 = 目标 != null ? [目标] : [];
    }
}

// 战斗管理器
public class 战斗管理器(
    事件总线 事件总线,
    技能管理器 技能管理器,
    怪物AI管理器 怪物AI管理器,
    效果管理器 效果管理器,
    ILogger<战斗管理器> 日志器)
{
    public 事件总线 事件总线 { get; } = 事件总线;
    private readonly 技能管理器 _技能管理器 = 技能管理器;
    private readonly 怪物AI管理器 _怪物AI管理器 = 怪物AI管理器;
    private readonly 效果管理器 _效果管理器 = 效果管理器;
    private readonly ILogger<战斗管理器> _日志器 = 日志器;
    private readonly 回合制战斗系统 _回合制战斗系统 = new(); // 添加回合制战斗系统

    private readonly ConcurrentDictionary<Guid, 战斗上下文> _战斗上下文字典 = new();
    
    // 添加决策超时检查任务
    private readonly ConcurrentDictionary<Guid, CancellationTokenSource> _决策超时令牌字典 = new();

    /// <summary>
    /// 开始战斗
    /// </summary>
    public async Task<战斗结果> 开始战斗(副本配置 副本, List<玩家> 玩家队伍, bool 自动战斗 = false)
    {
        _日志器.LogInformation("开始游戏副本战斗: {副本名称}", 副本.名称);

        // 创建战斗上下文
        var 战斗上下文 = new 战斗上下文
        {
            副本 = 副本,
            玩家队伍 = 玩家队伍,
            怪物队伍 = 副本.怪物生成配置列表.SelectMany(m => 
                Enumerable.Repeat(m.怪物详情!, m.数量)).ToList(),
            战斗管理器 = this
        };

        // 初始化战斗单位状态
        foreach (var 玩家 in 玩家队伍)
        {
            玩家.当前生命值 = 玩家.当前属性.生命值;
            玩家.当前魔法值 = 玩家.当前属性.魔法值;
        }

        foreach (var 怪物 in 战斗上下文.怪物队伍)
        {
            怪物.当前生命值 = 怪物.当前属性.生命值;
            怪物.当前魔法值 = 怪物.当前属性.魔法值;
        }

        // 注册战斗上下文
        _战斗上下文字典[战斗上下文.战斗ID] = 战斗上下文;

        // 发布战斗开始事件
        await 事件总线.发布事件(new 战斗开始事件 { 战斗上下文 = 战斗上下文 });

        // 战斗主循环
        var 战斗结果 = await 执行战斗循环(战斗上下文, 自动战斗);

        // 移除战斗上下文
        _战斗上下文字典.TryRemove(战斗上下文.战斗ID, out _);
        
        // 取消所有决策超时令牌
        if (_决策超时令牌字典.TryRemove(战斗上下文.战斗ID, out var 令牌源))
        {
            令牌源.Cancel();
        }

        return 战斗结果;
    }

    /// <summary>
    /// 执行战斗循环
    /// </summary>
    private async Task<战斗结果> 执行战斗循环(战斗上下文 战斗上下文, bool 自动战斗)
    {
        var 战斗结果 = new 战斗结果 { 战斗回合数 = 0 };

        while (!战斗上下文.是否结束)
        {
            战斗上下文.当前回合数++;
            战斗结果.战斗回合数 = 战斗上下文.当前回合数;
            战斗上下文.回合开始时间 = DateTime.Now;

            _日志器.LogDebug("开始回合 {回合数}", 战斗上下文.当前回合数);

            // 发布回合开始事件
            await 事件总线.发布事件(new 回合开始事件 
            { 
                战斗上下文 = 战斗上下文, 
                回合数 = 战斗上下文.当前回合数 
            });

            // 计算当前回合的行动顺序
            战斗上下文.当前回合行动顺序 = _回合制战斗系统.计算行动顺序(
                战斗上下文.玩家队伍, 
                战斗上下文.怪物队伍);
            战斗上下文.当前行动单位索引 = 0;

            // 按行动顺序执行回合
            await 执行回合按行动顺序(战斗上下文, 自动战斗);

            // 处理回合结束效果
            await 处理回合结束效果(战斗上下文);

            // 检查战斗是否结束
            检查战斗结束条件(战斗上下文, 战斗结果);

            // 清空决策
            战斗上下文.玩家决策.Clear();
        }

        // 发布战斗结束事件
        await 事件总线.发布事件(new 战斗结束事件 
        { 
            战斗上下文 = 战斗上下文, 
            玩家胜利 = 战斗结果.玩家胜利 
        });

        return 战斗结果;
    }

    /// <summary>
    /// 按行动顺序执行回合
    /// </summary>
    private async Task 执行回合按行动顺序(战斗上下文 战斗上下文, bool 自动战斗)
    {
        foreach (var 行动单位 in 战斗上下文.当前回合行动顺序)
        {
            // 检查单位是否还存活
            if (!行动单位.单位.是否存活)
                continue;

            // 根据单位类型执行相应行动
            if (行动单位.单位 is 玩家 玩家)
            {
                await 执行玩家行动(玩家, 战斗上下文, 自动战斗);
            }
            else if (行动单位.单位 is 怪物 怪物)
            {
                await 执行怪物行动(怪物, 战斗上下文);
            }

            // 检查战斗是否已结束
            if (战斗上下文.是否结束)
                break;
        }
    }

    /// <summary>
    /// 执行玩家行动
    /// </summary>
    private async Task 执行玩家行动(玩家 玩家, 战斗上下文 战斗上下文, bool 自动战斗)
    {
        if (自动战斗 || 玩家.是否自动战斗)
        {
            // 自动战斗决策
            var 决策 = _怪物AI管理器.生成玩家决策(玩家, 战斗上下文.怪物队伍);
            战斗上下文.玩家决策[玩家.Id] = 决策;
        }
        else
        {
            // 等待玩家决策
            var 决策 = await 等待玩家决策(玩家, 战斗上下文);
            if (决策 != null)
            {
                战斗上下文.玩家决策[玩家.Id] = 决策;
            }
            else
            {
                // 超时未决策，使用默认AI决策
                var 默认决策 = _怪物AI管理器.生成玩家决策(玩家, 战斗上下文.怪物队伍);
                战斗上下文.玩家决策[玩家.Id] = 默认决策;
            }
        }

        // 执行玩家决策
        await 执行玩家决策(玩家, 战斗上下文);
    }

    /// <summary>
    /// 等待玩家决策（带时间限制）
    /// </summary>
    private async Task<AI决策?> 等待玩家决策(玩家 玩家, 战斗上下文 战斗上下文)
    {
        try
        {
            // 创建超时令牌
            var 令牌源 = new CancellationTokenSource();
            _决策超时令牌字典[战斗上下文.战斗ID] = 令牌源;
            
            // 设置超时时间
            令牌源.CancelAfter(TimeSpan.FromSeconds(战斗上下文.回合时间限制));

            // 等待玩家提交决策或超时
            while (!令牌源.Token.IsCancellationRequested)
            {
                if (战斗上下文.玩家决策.TryGetValue(玩家.Id, out var 决策))
                {
                    // 检查决策是否在合理时间内提交
                    if ((DateTime.Now - 决策.提交时间).TotalSeconds <= 战斗上下文.回合时间限制)
                    {
                        return 决策;
                    }
                }
                
                // 短暂等待后再次检查
                await Task.Delay(100);
            }

            // 超时处理
            _日志器.LogInformation("玩家 {玩家名称} 决策超时", 玩家.名称);
            return null;
        }
        catch (Exception ex)
        {
            _日志器.LogError(ex, "等待玩家决策时发生错误");
            return null;
        }
    }

    /// <summary>
    /// 执行怪物行动
    /// </summary>
    private async Task 执行怪物行动(怪物 怪物, 战斗上下文 战斗上下文)
    {
        // 生成怪物决策
        var 决策 = _怪物AI管理器.生成怪物决策(怪物, 战斗上下文.玩家队伍);

        // 执行怪物行动
        await 执行怪物决策(怪物, 决策, 战斗上下文);
    }

    /// <summary>
    /// 执行玩家决策
    /// </summary>
    private async Task 执行玩家决策(玩家 玩家, 战斗上下文 战斗上下文)
    {
        if (!战斗上下文.玩家决策.TryGetValue(玩家.Id, out var 决策))
            return;

        switch (决策.行动类型)
        {
            case "攻击":
                if (决策.目标 != null)
                {
                    await 执行普通攻击(玩家, 决策.目标, 战斗上下文);
                }
                break;

            case "技能":
                if (!string.IsNullOrEmpty(决策.技能名称) && 决策.目标列表.Any())
                {
                    await _技能管理器.执行技能(玩家, 决策.技能名称, 决策.目标列表, this);
                }
                break;
        }
    }

    /// <summary>
    /// 执行怪物决策
    /// </summary>
    private async Task 执行怪物决策(怪物 怪物, AI决策 决策, 战斗上下文 战斗上下文)
    {
        switch (决策.行动类型)
        {
            case "攻击":
                if (决策.目标 != null)
                {
                    await 执行普通攻击(怪物, 决策.目标, 战斗上下文);
                }
                break;

            case "技能":
                if (!string.IsNullOrEmpty(决策.技能名称) && 决策.目标列表.Any())
                {
                    await _技能管理器.执行技能(怪物, 决策.技能名称, 决策.目标列表, this);
                }
                break;
        }
    }

    /// <summary>
    /// 执行普通攻击
    /// </summary>
    private async Task 执行普通攻击(战斗单位 攻击者, 战斗单位 目标, 战斗上下文 战斗上下文)
    {
        // 计算伤害
        var 伤害 = Math.Max(1, 攻击者.当前属性.物理攻击 - 目标.当前属性.物理防御 / 2);

        // 应用伤害
        目标.当前生命值 = Math.Max(0, 目标.当前生命值 - 伤害);

        _日志器.LogDebug("{攻击者} 对 {目标} 造成了 {伤害} 点伤害", 攻击者.名称, 目标.名称, 伤害);

        // 发布攻击事件
        await 事件总线.发布事件(new 攻击事件
        {
            攻击者 = 攻击者,
            受击者 = 目标,
            伤害值 = 伤害,
            战斗上下文 = 战斗上下文
        });

        // 发布受击事件
        await 事件总线.发布事件(new 受击事件
        {
            攻击者 = 攻击者,
            受击者 = 目标,
            伤害值 = 伤害,
            战斗上下文 = 战斗上下文
        });
        
        // 发布战斗状态更新事件
        await 发布战斗状态更新(战斗上下文, 目标);
    }

    /// <summary>
    /// 发布战斗状态更新
    /// </summary>
    private async Task 发布战斗状态更新(战斗上下文 战斗上下文, 战斗单位 单位)
    {
        await 事件总线.发布事件(new 战斗状态更新事件
        {
            战斗ID = 战斗上下文.战斗ID,
            单位ID = 单位.Id,
            当前生命值 = 单位.当前生命值,
            当前魔法值 = 单位.当前魔法值,
            最大生命值 = 单位.当前属性.生命值,
            最大魔法值 = 单位.当前属性.魔法值,
            是否存活 = 单位.是否存活
        });
    }

    /// <summary>
    /// 处理回合结束效果
    /// </summary>
    private async Task 处理回合结束效果(战斗上下文 战斗上下文)
    {
        // 处理所有战斗单位的回合结束效果
        var 所有单位 = 战斗上下文.玩家队伍.Cast<战斗单位>()
            .Concat(战斗上下文.怪物队伍)
            .Where(u => u.是否存活);

        foreach (var 单位 in 所有单位)
        {
            await _效果管理器.处理回合结束效果(单位, this);
            
            // 发布状态更新
            await 发布战斗状态更新(战斗上下文, 单位);
        }
    }

    /// <summary>
    /// 检查战斗结束条件
    /// </summary>
    private void 检查战斗结束条件(战斗上下文 战斗上下文, 战斗结果 战斗结果)
    {
        // 检查玩家是否全部死亡
        if (战斗上下文.玩家队伍.All(p => !p.是否存活))
        {
            战斗上下文.是否结束 = true;
            战斗结果.玩家胜利 = false;
            _日志器.LogInformation("游戏副本战斗失败");
            return;
        }

        // 检查怪物是否全部死亡
        if (战斗上下文.怪物队伍.All(m => !m.是否存活))
        {
            战斗上下文.是否结束 = true;
            战斗结果.玩家胜利 = true;
            战斗结果.获得经验 = 战斗上下文.副本.经验奖励;
            战斗结果.获得物品 = 战斗上下文.副本.通关奖励.ToList();
            _日志器.LogInformation("副本战斗胜利");
            return;
        }
    }

    /// <summary>
    /// 提交玩家决策
    /// </summary>
    public void 提交玩家决策(Guid 玩家Id, AI决策 决策)
    {
        // 在实际应用中，这里需要找到对应的战斗上下文
        // 简化处理，假设只有一个战斗
        var 战斗上下文 = _战斗上下文字典.Values.FirstOrDefault();
        if (战斗上下文 != null)
        {
            决策.提交时间 = DateTime.Now; // 记录提交时间
            战斗上下文.玩家决策[玩家Id] = 决策;
        }
    }

    /// <summary>
    /// 获取战斗上下文
    /// </summary>
    public 战斗上下文? 获取战斗上下文(Guid 战斗ID)
    {
        return _战斗上下文字典.TryGetValue(战斗ID, out var 战斗上下文) ? 战斗上下文 : null;
    }
    
    /// <summary>
    /// 处理玩家决策
    /// </summary>
    public void 处理玩家决策(Guid 玩家Id, AI决策 决策)
    {
        提交玩家决策(玩家Id, 决策);
    }
}